package com.example.bluetoothclicker.normal

import BluetoothReceiver
import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothProfile
import android.bluetooth.BluetoothSocket
import android.content.Context
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat
import java.io.IOException
import java.util.UUID

object BluetoothManager {

    private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
    private val discoveredDevicesSet = mutableSetOf<BluetoothDevice>()
    private val pairedDevicesSet = mutableSetOf<BluetoothDevice>()
    private val connectedDevices = mutableListOf<BluetoothDevice>()
    private val scanHandler = Handler(Looper.getMainLooper())
    private var isScanning = false
    private var isCooling = false
    private var applicationContext: Context? = null
    private var isInitialized = false
    private var onScanStateChanged: ((Boolean) -> Unit)? = null
    private var onDeviceDiscovered: ((BluetoothDevice) -> Unit)? = null
    private var onDevicePaired: ((BluetoothDevice) -> Unit)? = null
    private var onConnectionStateChanged: ((BluetoothDevice, Boolean) -> Unit)? = null
    private var onConnectionStateChanged_Home: ((BluetoothDevice, Boolean) -> Unit)? = null
    private var autoScanRunnable: Runnable? = null


    private var bluetoothGatt: BluetoothGatt? = null

    // 定义 GATT Battery Service 和特性 UUID
    private val BATTERY_SERVICE_UUID = UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb")
    private val BATTERY_LEVEL_UUID = UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")

    private const val TAG = "BluetoothManager"
    private var bluetoothSocket: BluetoothSocket? = null

    // 初始化 BluetoothManager
    fun initialize(context: Context) {
        if (isInitialized) return
        applicationContext = context.applicationContext

        val filter = IntentFilter().apply {
            addAction(BluetoothDevice.ACTION_FOUND)
            addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
            addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
            addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
        }

        try {
            applicationContext?.registerReceiver(BluetoothReceiver, filter)
        } catch (e: IllegalArgumentException) {
            Log.w(TAG, "广播接收器已注册，跳过重新注册")
        }

        // 设置广播回调
        BluetoothReceiver.setOnDeviceDiscoveredListener { device ->
            if (discoveredDevicesSet.add(device)) {
                onDeviceDiscovered?.invoke(device)
            }
        }

        BluetoothReceiver.setOnPairingCompletedListener { device ->
            discoveredDevicesSet.remove(device)
            if (pairedDevicesSet.add(device)) {
                onDevicePaired?.invoke(device)
            }
        }

        // 新增监听设备连接状态变化
        BluetoothReceiver.setOnConnectionStateChangedListener { device, isConnected ->
            if (isConnected) {
                if (!connectedDevices.contains(device)) {
                    connectedDevices.add(device)
                    Toast.makeText(applicationContext, "已连接: ${device.name}", Toast.LENGTH_SHORT).show()
                }
            } else {
                connectedDevices.remove(device)
                Toast.makeText(applicationContext, "已断开连接: ${device.name}", Toast.LENGTH_SHORT).show()
            }
            onConnectionStateChanged?.invoke(device, isConnected)
            onConnectionStateChanged_Home?.invoke(device, isConnected)
        }

        // 在初始化时同步获取当前已连接设备
        connectedDevices.clear()
        connectedDevices.addAll(getCurrentlyConnectedDevices())

        isInitialized = true
    }



    private fun getCurrentlyConnectedDevices(): List<BluetoothDevice> {
        val connectedDevices = mutableListOf<BluetoothDevice>()

        // 检查权限
        if (!ensurePermissions()) {
            Log.w(TAG, "缺少必要权限，无法获取已连接设备")
            return connectedDevices
        }

        bluetoothAdapter?.let { adapter ->
            // 遍历配对设备，检查其连接状态
            val pairedDevices = adapter.bondedDevices
            for (device in pairedDevices) {
                try {
                    val method = device.javaClass.getMethod("isConnected")
                    val isConnected = method.invoke(device) as Boolean
                    if (isConnected) {
                        connectedDevices.add(device)
                    }
                } catch (e: Exception) {
                    Log.e(TAG, "无法获取设备连接状态: ${device.name}", e)
                }
            }
        }

        // 获取通过 BluetoothManager 管理的已连接设备
        val bluetoothManager = applicationContext?.getSystemService(Context.BLUETOOTH_SERVICE) as? android.bluetooth.BluetoothManager
        bluetoothManager?.let { manager ->
            val profiles = listOf(BluetoothProfile.GATT, BluetoothProfile.A2DP, BluetoothProfile.HEADSET)
            for (profile in profiles) {
                try {
                    val profileDevices = manager.getConnectedDevices(profile)
                    connectedDevices.addAll(profileDevices)
                } catch (e: Exception) {
                    Log.e(TAG, "无法获取协议设备: Profile $profile", e)
                }
            }
        }

        return connectedDevices.distinct() // 去重
    }


    // 获取当前已连接设备列表
    fun getConnectedDevices(): List<BluetoothDevice> {
        return connectedDevices.toList()
    }

    // 设置连接状态回调
    fun setOnConnectionStateChangedListener(callback: (BluetoothDevice, Boolean) -> Unit) {
        onConnectionStateChanged = callback
    }

    fun setOnConnectionStateChangedListener_Home(callback: (BluetoothDevice, Boolean) -> Unit) {
        onConnectionStateChanged_Home = callback
    }

    // 设置扫描状态回调
    fun setOnScanStateChangedListener(callback: (Boolean) -> Unit) {
        onScanStateChanged = callback
    }

    // 设置设备发现回调
    fun setOnDeviceDiscoveredListener(callback: (BluetoothDevice) -> Unit) {
        onDeviceDiscovered = callback
    }

    // 设置设备配对成功回调
    fun setOnDevicePairedListener(callback: (BluetoothDevice) -> Unit) {
        onDevicePaired = callback
    }

    // 开始扫描设备
    fun startDiscovery() {
        if (!ensurePermissions()) return
        bluetoothAdapter?.let {
            if (!it.isDiscovering) {
                it.startDiscovery()
                Log.d("BluetoothManager", "开始扫描设备")
                Toast.makeText(applicationContext, "开始扫描设备", Toast.LENGTH_SHORT).show()
                discoveredDevicesSet.clear()
                onScanStateChanged?.invoke(true) // 触发扫描开始状态回调
            }
        }
    }

    // 停止扫描设备
    fun stopDiscovery() {
        bluetoothAdapter?.let {
            if (it.isDiscovering) {
                it.cancelDiscovery()
                Log.d("BluetoothManager", "停止扫描设备")
                applicationContext?.let { context ->
                    Toast.makeText(context, "停止扫描设备", Toast.LENGTH_SHORT).show()
                }
                onScanStateChanged?.invoke(false) // 触发扫描停止状态回调
                if (isScanning){
                    isCooling = true
                }
            }
        }
    }

    // 启动自动扫描
    fun startAutoScan(interval: Long = 30000L, duration: Long = 10000L) {
        // 如果正在扫描并且未处于冷却状态，直接返回，防止重复触发
        if (isScanning && !isCooling) return

        // 如果处于冷却状态，停止冷却，立即开始新一轮扫描
        if (isScanning && isCooling) {
            scanHandler.removeCallbacksAndMessages(null) // 清理之前的任务
            isCooling = false
        }

        // 标记为正在扫描中
        isScanning = true

        // 定义扫描任务
        autoScanRunnable = object : Runnable {
            override fun run() {
                if (isScanning) {
                    startDiscovery() // 开始扫描
                    scanHandler.postDelayed({
                        stopDiscovery() // 停止扫描
                        isCooling = true // 标记冷却状态
                        scanHandler.postDelayed(this, interval) // 冷却后重新扫描
                    }, duration) // 扫描持续时间
                }
            }
        }

        // 立即执行扫描任务
        scanHandler.post(autoScanRunnable!!)
    }

    // 停止自动扫描
    fun stopAutoScan() {
        if (isScanning) {
            isScanning = false
            isCooling = false
            scanHandler.removeCallbacksAndMessages(null)
            autoScanRunnable = null
            stopDiscovery()
        }
    }

    // 获取已配对设备列表
    fun getPairedDevices(): List<BluetoothDevice> {
        return bluetoothAdapter?.bondedDevices?.toList() ?: emptyList()
    }

    // 确保权限
    private fun ensurePermissions(): Boolean {
        applicationContext?.let { context ->
            val permissions = listOf(
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN,
                Manifest.permission.ACCESS_FINE_LOCATION
            )
            val missingPermissions = permissions.filter {
                ActivityCompat.checkSelfPermission(context, it) != PackageManager.PERMISSION_GRANTED
            }
            if (missingPermissions.isNotEmpty()) {
                Log.e(TAG, "缺少权限: ${missingPermissions.joinToString()}")
                Toast.makeText(context, "请授予蓝牙和位置权限", Toast.LENGTH_LONG).show()
                return false
            }
            return true
        } ?: throw IllegalStateException("BluetoothManager 未初始化。")
    }

    /**
     * 连接到指定设备
     */
    fun connectToDevice(device: BluetoothDevice) {
        // 检查是否已配对
        if (device.bondState != BluetoothDevice.BOND_BONDED) {
            Log.d(TAG, "设备未配对，尝试配对: ${device.name} (${device.address})")
            Toast.makeText(applicationContext, "设备未配对，尝试配对: ${device.name} (${device.address})", Toast.LENGTH_SHORT).show()
            pairDevice(device)
        } else {
            Log.d(TAG, "设备已配对，尝试连接: ${device.name} (${device.address})")
            Toast.makeText(applicationContext, "设备已配对，尝试连接: ${device.name} (${device.address})", Toast.LENGTH_SHORT).show()
            connectToPairedDevice(device)
        }
    }

    /**
     * 发起配对请求
     */
    private fun pairDevice(device: BluetoothDevice) {
        try {
            // 通过反射调用配对方法
            val method = device.javaClass.getMethod("createBond")
            method.invoke(device)
            Log.d(TAG, "已发送配对请求: ${device.name} (${device.address})")

            // 配对成功后监听配对状态的变化，通过回调触发连接
            BluetoothReceiver.setOnPairingCompletedListener { pairedDevice ->
                if (pairedDevice.address == device.address) {
                    Log.d(TAG, "配对成功: ${device.name} (${device.address})，尝试连接")
                    Toast.makeText(applicationContext, "配对成功: ${device.name} (${device.address})，尝试连接", Toast.LENGTH_SHORT).show()
                    connectToPairedDevice(device)
                }
            }

        } catch (e: Exception) {
            Log.e(TAG, "设备配对失败: ${device.name} (${device.address})", e)
        }
    }

    /**
     * 连接到已配对的设备
     */
    private fun connectToPairedDevice(device: BluetoothDevice) {
        Thread {
            try {
                val uuid = if (device.uuids.isNullOrEmpty()) {
                    UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // 默认 UUID
                } else {
                    device.uuids[0].uuid
                }

                Log.d(TAG, "尝试连接到设备: ${device.name} (${device.address}) 使用 UUID: $uuid")

                bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid)

                // 停止扫描避免干扰连接
                bluetoothAdapter?.cancelDiscovery()

                // 延迟连接以确保设备状态可用
                Thread.sleep(1000)

                // 建立连接
                bluetoothSocket?.connect()
                Log.d(TAG, "设备连接成功: ${device.name} (${device.address})")

                onConnectionSuccess(device)

            } catch (e: IOException) {
                Log.e(TAG, "设备连接失败: ${device.name} (${device.address})", e)
                runOnMainThread {
                    Toast.makeText(applicationContext, "设备连接失败: ${device.name}", Toast.LENGTH_SHORT).show()
                }
                onConnectionFailed(device)

                try {
                    bluetoothSocket?.close()
                } catch (closeException: IOException) {
                    Log.e(TAG, "关闭连接时发生错误", closeException)
                }
            }
        }.start()
    }

    /**
     * 在主线程上运行指定的任务
     */
    private fun runOnMainThread(action: () -> Unit) {
        Handler(Looper.getMainLooper()).post(action)
    }


    /**
     * 连接成功回调
     */
    private fun onConnectionSuccess(device: BluetoothDevice) {
        Log.d(TAG, "已成功连接到设备: ${device.name} (${device.address})")

        if (!connectedDevices.contains(device)) {
            connectedDevices.add(device)
        }

        runOnMainThread {
            Toast.makeText(applicationContext, "已连接: ${device.name}", Toast.LENGTH_SHORT).show()
            onConnectionStateChanged?.invoke(device, true) // 通知连接成功
        }
    }

    /**
     * 连接失败回调
     */
    private fun onConnectionFailed(device: BluetoothDevice) {
        Log.d(TAG, "无法连接到设备: ${device.name} (${device.address})")

        runOnMainThread {
            Toast.makeText(applicationContext, "连接失败: ${device.name}", Toast.LENGTH_SHORT).show()
            onConnectionStateChanged?.invoke(device, false) // 通知连接失败
        }
    }

    /**
     * 获取设备电量
     */
    fun getDeviceBatteryLevel(
        context: Context,
        device: BluetoothDevice,
        onBatteryLevelRead: (Int) -> Unit
    ) {

        device.connectGatt(context, false, object : BluetoothGattCallback() {
            override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    gatt.discoverServices()
                }
            }

            override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    val batteryService = gatt.getService(UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb"))
                    val batteryLevelCharacteristic = batteryService?.getCharacteristic(
                        UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")
                    )
                    if (batteryLevelCharacteristic != null) {
                        gatt.readCharacteristic(batteryLevelCharacteristic)
                    }
                }
            }

            override fun onCharacteristicRead(
                gatt: BluetoothGatt,
                characteristic: BluetoothGattCharacteristic,
                status: Int
            ) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    val batteryLevel = characteristic.value[0].toInt()
                    Toast.makeText(applicationContext, "电池电量: ${batteryLevel}", Toast.LENGTH_SHORT).show()
                    onBatteryLevelRead(batteryLevel)
                }
                gatt.close() // 释放资源
            }
        })
    }


    /**
     * 断开 GATT 连接
     */
    fun disconnectGatt() {
        bluetoothGatt?.close()
        bluetoothGatt = null
    }

    // 释放资源
    fun releaseScan() {
        if (!isInitialized) return
        applicationContext?.unregisterReceiver(BluetoothReceiver)
        stopDiscovery()
        stopAutoScan()
        discoveredDevicesSet.clear()
    }

    fun release() {
        if (!isInitialized) return
        applicationContext?.unregisterReceiver(BluetoothReceiver)
        stopDiscovery()
        stopAutoScan() // 停止自动扫描
        bluetoothSocket?.close()
        bluetoothSocket = null
        isInitialized = false
    }

    fun sendMessageToDevice(message: String): Boolean {
        if (bluetoothSocket == null || !bluetoothSocket!!.isConnected) {
            Log.e(TAG, "未连接到任何设备，无法发送消息")
            return false
        }

        return try {
            val outputStream = bluetoothSocket!!.outputStream
            outputStream.write(message.toByteArray())
            outputStream.flush()
            Log.d(TAG, "消息发送成功: $message")
            true
        } catch (e: IOException) {
            Log.e(TAG, "消息发送失败", e)
            false
        }
    }

    // 定义消息接收回调
    private var onMessageReceived: ((String) -> Unit)? = null

    /**
     * 开始监听消息
     */
    fun startListeningForMessages() {
        if (bluetoothSocket == null || !bluetoothSocket!!.isConnected) {
            Log.e(TAG, "未连接到任何设备，无法接收消息")
            return
        }

        Thread {
            try {
                val inputStream = bluetoothSocket!!.inputStream
                val buffer = ByteArray(1024)
                var bytes: Int

                while (bluetoothSocket!!.isConnected) {
                    // 读取输入流中的数据
                    bytes = inputStream.read(buffer)
                    val message = String(buffer, 0, bytes)
                    Log.d(TAG, "接收到消息: $message")
                    onMessageReceived?.invoke(message) // 触发回调
                }
            } catch (e: IOException) {
                Log.e(TAG, "消息接收失败", e)
            }
        }.start()
    }

    /**
     * 设置消息接收回调
     */
    fun setOnMessageReceivedListener(callback: ((String) -> Unit)?) {
        onMessageReceived = callback
    }

}
